import numpy as np
import matplotlib.pyplot as plt
#超平面模型
def model(x,theta):
    return x.dot(theta)
#sigmoid函数
def sigmoid(z):
    return 1/(1+np.exp(-z))
#代价函数
#theta模型参数
#lamda:正则化系数
def cost(h,y,theta,lamda):
    m=len(h)
    #r：正则化项
    r=lamda/(2*m)*np.sum(theta**2)
    return -1/m*np.sum(y*np.log(h)+(1-y)*np.log(1-h))+r
#梯度下降
#lamda：正则化系数
def grad(x,y,lamda,iter0=5000,alpha=0.01):
    m,n=x.shape
    theta=np.zeros(n)
    J=np.zeros(iter0)
    for i in range(iter0):
        z=model(x,theta)
        h=sigmoid(z)
        J[i]=cost(h,y,theta,lamda)
        #r：正则化项
        r=lamda/m*theta
        dt=1/m*x.T.dot(h-y)+r
        theta-=alpha*dt
    return h,theta,J
#准确率
def score(h,y):
    return np.mean(y==[h>0.5])

if __name__ == '__main__':
    #加载数据
    data=np.loadtxt('ex2data1.txt',delimiter=',')
    #切分数据
    x=data[:,:-1]
    y=data[:,-1]
    #特征缩放  标准化
    miu=np.mean(x,axis=0)
    sigma=np.std(x,axis=0)
    x=(x-miu)/sigma
    # 拼接X
    X=np.c_[np.ones(len(x)),x]
    #正则化系数设置为0、3、6
    #训练模型
    h0, theta0, J0=grad(X,y,0)
    h3, theta3, J3=grad(X,y,3)
    h6, theta6, J6=grad(X,y,6)
    #画出不同lamda的代价函数图像
    plt.plot(J0)
    plt.plot(J3)
    plt.plot(J6)
    plt.show()